#ifndef SYNSHAREMEM_H
#define SYNSHAREMEM_H

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QSharedMemory>
#include <QSystemSemaphore>

/***************************************************
 * 类名：共享内存及同步封装类
 * 1、使用方法: 查看ExampleWindow类使用
 * 2、读写匹配方法
 * （1）-（3）无条件写入模式 + 条件读取模式
 * （1）-（4）无条件写入模式 + 约定读取模式
 * （2）-（4）约定写入模式 + 约定读取模式
 *
 * *************************************************/
class SynShareMem : public QThread
{
    Q_OBJECT
public:
    enum Type
    {
        eWrite_1_sema = 1,  //无条件写入
        eWrite_2_sema = 2,  //约定写入（等待其他进程读取后才能写入）
        eRead_1_sema = 3,   //条件读取
        eRead_2_sema = 4    //约定读取（读取后释放写入的条件，与eWrite_2_sema模式配合）
    };
public:
    explicit SynShareMem(Type type,QString memKey, unsigned int size, QString semaKey, QObject *parent = nullptr);
    ~SynShareMem();

    //约定模式下，未接收结束就写入会写入失败，所以需要等待readFinished信号
    //读取模式下不允许写入，写入返回0（失败）
    bool writeMem (char *data, int size);    //写入共享内存-固定长度
    //void writeMem(QByteArray data);         //非固定长度

    int readMem(char *data,int size);

    //目前所有模式都可以清空
    void cleanMem(char data = 0x00);

    void stop();
protected:
    void run();

signals:
    void haveRead(char *data,int size);    //共享内存读取一次就发送一次，只有读取模式下有效
    //void haveRead(QByteArray data);    //非固定长度
    void readFinished();    //只有双锁写入模式下有效，标识对方进程已经读取共享内存数据，此时调用writeMem函数不会被阻塞

private:
    bool quitFlag;
    Type mType;     //类型
    QSharedMemory *shareMem;

    QSystemSemaphore *mSema_W2R;
    QSystemSemaphore *mSema_R2W;     //信号量-读取标志

    char *mShareData;           //缓存数据段
    int mShareSize;    //共享内存大小

    QSharedMemory *creatShareMemory(QString key, int size, bool isWrite = 1);
    void relaseShareMemory(QSharedMemory *mem);
    bool writeShareMemory(QSharedMemory *mem, char *data, int size);
    void readShareMemory(QSharedMemory *mem, char *data, uint size);
};

#endif // SYNSHAREMEM_H
